/**  
 * cp1.c  
 *     cp - 使用 read 和 write，并保留可调节的缓冲区大小  
 *  
 *     用法: cp1  源文件 目标文件  
 */  

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <fcntl.h>  
#include <errno.h>  
#include <string.h>  

#define BUFFERSIZE 4096  
#define COPYMODE 0644  

void handle_error(const char *msg1, const char *msg2);  

int main(int argc, char *argv[]) {  
    int in_fd, out_fd;  
    ssize_t n_chars;  
    char buf[BUFFERSIZE];  

    /* 检查参数数量 */  
    if (argc != 3) {  
        fprintf(stderr, "用法: %s 源文件 目标文件\n", argv[0]);  
        exit(EXIT_FAILURE);  
    }  

    /* 打开源文件 */  
    in_fd = open(argv[1], O_RDONLY);  
    if (in_fd == -1) {  
        handle_error("无法打开源文件 ", argv[1]);  
    }  

    /* 创建（或截断）目标文件 */  
    out_fd = creat(argv[2], COPYMODE);  
    if (out_fd == -1) {  
        close(in_fd);  
        handle_error("无法创建目标文件 ", argv[2]);  
    }  

    /* 复制文件内容 */  
    while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0) {  
        ssize_t bytes_written = 0;  
        ssize_t result;  

        while (bytes_written < n_chars) {  
            result = write(out_fd, buf + bytes_written, n_chars - bytes_written);  
            if (result == -1) {  
                close(in_fd);  
                close(out_fd);  
                handle_error("写入目标文件时出错 ", argv[2]);  
            }  
            bytes_written += result;  
        }  
    }  

    if (n_chars == -1) {  
        close(in_fd);  
        close(out_fd);  
        handle_error("读取源文件时出错 ", argv[1]);  
    }  

    /* 关闭文件描述符 */  
    if (close(in_fd) == -1) {  
        fprintf(stderr, "关闭源文件时出错: %s\n", strerror(errno));  
    }  

    if (close(out_fd) == -1) {  
        fprintf(stderr, "关闭目标文件时出错: %s\n", strerror(errno));  
    }  

    return EXIT_SUCCESS;  
}  

/**  
 * 处理错误并退出程序  
 * @param msg1 错误消息的前半部分  
 * @param msg2 错误消息的后半部分（通常是文件名）  
 */  
void handle_error(const char *msg1, const char *msg2) {  
    fprintf(stderr, "错误: %s%s - %s\n", msg1, msg2, strerror(errno));  
    exit(EXIT_FAILURE);  
}